/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc. 
 *  
 * SPDX-License-Identifier: Apache-2.0.
 * 
 * @Date: 2021-09-15 19:46:05
 * @LastEditTime: 2021-09-16 17:06:56
 * @Description:  This files is for 
 * 
 * @Modify History: 
 *  Ver   Who        Date         Changes
 * ----- ------     --------    --------------------------------------
 */
#include <string.h>
#include "ft_assert.h"
#include "parameters.h"
#include "f_sdio.h"
#include "f_sdio_hw.h"

extern u32 FSdioBusModeSwrReset(FSdioCtrl *ctrl_p);

u32 FSdioIDmaInit(FSdioCtrl *ctrl_p)
{
    FT_ASSERTNONERETURN(ctrl_p);
    u32 ret = FSDIO_SUCCESS;

    FSDIO_SET_BITS(ctrl_p, FSDIO_REG_CNTRL_OFFSET, FSDIO_CNTRL_DMA_ENABLE);
    FSDIO_WRITE_REG(ctrl_p, FSDIO_REG_BUS_MODE_OFFSET, 0x0);
    ret = FSdioBusModeSwrReset(ctrl_p);
    if (FSDIO_SUCCESS != ret)
        return ret;

    FSdioSetIntrMask(ctrl_p, FSDIO_IDMA_INTR, 
                     FSDIO_DMAC_INT_ENA_NIS |
                     FSDIO_DMAC_INT_ENA_RI |
                     FSDIO_DMAC_INT_ENA_TI, TRUE);

    return ret;
}

u32 FSdioIDmaTblInit(FSdioCtrl *ctrl_p, FSdioIdmaTbl *dma_p)
{
    FT_ASSERTZERONUM(ctrl_p && dma_p);
    FSdioIdmaDesc *desc = dma_p->idma_desc;
    uintptr next_dma_addr;
    u32 i;

    memset(desc, 0 , sizeof(FSdioIdmaDesc) * dma_p->idma_desc_sz); /* this clears "owned by IDMAC" bits */

    for (i = 0; i < (dma_p->idma_desc_sz - 1); i++)
    {
        next_dma_addr = dma_p->idma_addr + sizeof(FSdioIdmaDesc) * (i + 1);
        desc[i].desc_lo = LOWER_32_BITS(next_dma_addr);
        desc[i].desc_hi = UPPER_32_BITS(next_dma_addr);
        desc[i].attribute = 0;
        desc[i].non1 = 0;
        desc[i].len = 0;
        desc[i].non2 = 0;
    }

    return FSdioBusModeSwrReset(ctrl_p);
}

void FSdioWriteIdmaDesc(FSdioCtrl *ctrl_p, FSdioIdmaDesc *desc_p, uintptr addr, u32 len, u32 attribute)
{
    FT_ASSERTVOID(ctrl_p && desc_p);

    desc_p->attribute = attribute;
    desc_p->len = len;
    desc_p->addr_lo = LOWER_32_BITS(addr);
    desc_p->addr_hi = UPPER_32_BITS(addr);

    FSDIO_INFO("addr_lo: 0x%x, addr_hi: 0x%x", desc_p->addr_lo, desc_p->addr_hi);

    if (FSDIO_IDMAC_DES0_LD & attribute) /* for the last trans desc */
    {
        desc_p->addr_lo = 0;
        desc_p->addr_hi = 0;
    }

    return;
}

void FSdioStopIdma(FSdioCtrl *ctrl_p)
{
    FT_ASSERTVOID(ctrl_p);

    FSDIO_CLR_BITS(ctrl_p, FSDIO_REG_CNTRL_OFFSET, FSDIO_CNTRL_USE_INTERNAL_DMAC);
    FSdioCtrlReset(ctrl_p, FSDIO_CNTRL_DMA_RESET);
    FSDIO_CLR_BITS(ctrl_p, FSDIO_REG_BUS_MODE_OFFSET, FSDIO_BUS_MODE_DE | FSDIO_BUS_MODE_FB);

    return;
}